<?php
namespace service\proxy;

const ROOT_PATH = __DIR__.DIRECTORY_SEPARATOR;

require ROOT_PATH.'curl.php';
require ROOT_PATH.'proxylist.php';
require ROOT_PATH.'redis.php';
require ROOT_PATH.'proxy_analysis_pool.php';

use service\proxy\redis as Redis;

/**
 * 每小时一次,移动到总的里面.
 * 每小时的做一次计数
 */



class Main
{
    protected static $ip_pool;

    /**
     * dispatch
     *
     * @return void
     */
    public function dispatch()
    {
        global $argv;
        if(isset($argv) && count($argv) > 1){
            date_default_timezone_set('PRC');
            static::ipPool()->updateOnDestruct(false);
            $this->collectProxy($argv[1]);
            exit;
        }
        die('for cli used only and must provide some valide params');
    }

    /**
     * ipPool
     *
     * @return service\proxy\proxylist
     */
    public static function ipPool()
    {
        if(static::$ip_pool === null){
            static::$ip_pool = proxylist::getInstance('proxy_analysis_pool');
        }
        return static::$ip_pool;
    }

    protected function collectProxy($type = null)
    {
        switch ($type) {
            //每小时执行
            case 'summary':
                if($ips = static::ipPool()->getAll() and is_array($ips)){
                    $pool_name = static::keyBuilder('kdl_iplist', true);
                    if(!$this->hasSummeryRecord($pool_name)){
                        $this->addIpToPool($ips, $pool_name);
                        static::ipPool()->drop($ips);
                    }
                }
                break;
            //每分钟执行
            case 'update':
                $old_len = static::ipPool()->getIpPoolLength();
                static::ipPool()->renew([], true);
                $new_len = static::ipPool()->getIpPoolLength();
                $this->setUpdateInfo($new_len - $old_len);

                break;
            case 'clear':
                static::ipPool()->clearIpPool(proxylist::GOOD_IP);
                break;
            default:
                die('nothing happend');
                break;
        }
    }

    /**
     * hasSummeryRecord
     *
     * @param  string  $key
     * @return boolean
     */
    protected function hasSummeryRecord($key)
    {
        return $key ? Redis::hExists(self::keyBuilder('proxy_analysis_pool_info'), (string) $key) : false;
    }

    /**
     * addIpToPool
     *
     * @param string|array $ip
     * @param string $pool_name
     * @return integer|void
     */
    protected function addIpToPool($ip, $pool_name)
    {
        if (is_string($ip) && (bool) trim($ip)) {
            $ip = [$ip];
        }
        if (is_array($ip) && count($ip)) {
            $this->setPoolInfo($pool_name, count($ip));
            return Redis::sAdd($pool_name, ...$ip);
        }
    }

    /**
     * setPoolInfo
     *
     * @param string $key
     * @param string $val
     */
    protected function setPoolInfo($key, $val)
    {
        return Redis::hSetnx(self::keyBuilder('proxy_analysis_pool_info') ,(string)$key, (string)$val);
    }

    /**
     * setPoolInfo
     *
     * @param string $key
     * @param string $val
     */
    protected function setUpdateInfo($new_count = '')
    {
        return Redis::lPush(self::keyBuilder('proxy_analysis_update_info'), $new_count.'@'.date('Y-m-d H:i:s'));
    }

    /**
     * keyBuilder
     *
     * @return string
     */
    public static function keyBuilder($key = '', $append_hour = false)
    {
        if(!is_string($key) || $key === ''){
            static::error_logger('invalid key for keyBuilder'. $key);
        }
        if($append_hour){
            $key .= date('_Y_m_d_H');
        }
        return '__proxy_analysis_'.$key;
    }

    /**
     * error logger
     *
     * @param  mixed $msg
     * @return void
     */
    protected static function error_logger($msg)
    {
        // $file = __DIR__.DIRECTORY_SEPARATOR.'proxy_analysis_error.log';
        // file_put_contents($file, ((string) $msg)."\n", FILE_APPEND);
        return Redis::lPush(static::keyBuilder('proxy_analysis_error_log'), date('Y-m-d H:i:s').' : '.((string) $msg));
    }
}



(new Main())->dispatch();



